package fr.umlv.m2.jee.spij.service.schedule.report;

import fr.umlv.m2.jee.spij.persistence.education.*;
import fr.umlv.m2.jee.spij.persistence.education.dao.*;
import fr.umlv.m2.jee.spij.service.ldap.authentification.DisplayActor;
import fr.umlv.m2.jee.spij.service.schedule.Assignment;
import org.richfaces.model.CalendarDataModel;
import org.richfaces.model.CalendarDataModelItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Calendar that dipslays report.
 *
 * @author thomas magny
 */
@Component("calendarDataModelReportImpl")
public class CalendarDataModelReportImpl implements
        CalendarDataModel, Assignment {

    /**
     * Calendar instance.
     */
    private final Calendar calendar = Calendar.getInstance();

    /**
     * list of fieldwork.
     */
    private final List<FieldWork> fieldworkList = new ArrayList<FieldWork>();

    /**
     * list of project.
     */
    private final List<Project> projectList = new ArrayList<Project>();

    /**
     * list of partial.
     */
    private final List<Partial> partialList = new ArrayList<Partial>();

    /**
     * list of remedial.
     */
    private final List<Remedial> remedialList = new ArrayList<Remedial>();

    /**
     * the actor.
     */
    private DisplayActor actor;

    /**
     * The unit DAO.
     */
    @Autowired
    private HibernateUnitDAO unitDAO;

    /**
     * the field work DAO.
     */
    @Autowired
    private HibernateFieldWorkDAO fieldWorkDAO;

    /**
     * The project DAO.
     */
    @Autowired
    private HibernateProjectDAO projectDAO;

    /**
     * The partial DAO.
     */
    @Autowired
    private HibernatePartialDAO partialDAO;

    /**
     * the remedial DAO.
     */
    @Autowired
    private HibernateRemedialDAO remedialDAO;

    /**
     * @param newActor the actor to set.
     */
    @Override
    public final void setUser(final DisplayActor newActor) {
        this.actor = newActor;
    }

    /**
     * @param dates array of date that is displayed into the calendar.
     *
     * @return an array of calendar item.
     */
    @Override
    @Transactional(readOnly = false)
    public final CalendarDataModelItem[] getData(final Date[] dates) {
        storeData();

        final CalendarDataModelItem[] calendarDataModelItems =
                new CalendarDataModelItem[dates.length];

        for (int i = 0; i < dates.length; i++) {
            calendar.setTime(dates[i]);

            CalendarDataModelReportItemImpl item =
                    new CalendarDataModelReportItemImpl();

            for (FieldWork fieldWork : fieldworkList) {
                if (fieldWork.getDeadLine() != null) {
                    if (fieldWork.getDeadLine().dayOfYear().get()
                            == calendar.get(Calendar.DAY_OF_YEAR)) {
                        addDataModelItem(item, fieldWork);
                    }
                }
            }
            for (Project project : projectList) {
                if (project.getDeadLine().dayOfYear().get()
                        == calendar.get(Calendar.DAY_OF_YEAR)) {
                    addDataModelItem(item, project);
                }
            }
            for (Partial partial : partialList) {
                if (partial.getDuration().getStart().dayOfYear().get()
                        == calendar.get(Calendar.DAY_OF_YEAR)) {
                    addDataModelItem(item, partial);
                }
            }
            for (Remedial remedial : remedialList) {
                if (remedial.getDuration().getStart().dayOfYear().get()
                        == calendar.get(Calendar.DAY_OF_YEAR)) {
                    addDataModelItem(item, remedial);
                }
            }
            calendarDataModelItems[i] = item;
        }
        return calendarDataModelItems;
    }

    /**
     * store datas.
     */
    private void storeData() {
        remedialList.clear();
        partialList.clear();
        projectList.clear();
        fieldworkList.clear();

        final List<Unit> units = unitDAO.findAll();

        for (Unit unit : units) {
            final List<FieldWork> fieldworks =
                    fieldWorkDAO.findByLdapActorAndUnitId(
                            unit.getId(),
                            actor.getLogin(),
                            actor.getType());
            if (fieldworks != null) {
                fieldworkList.addAll(fieldworks);
            }
            final List<Partial> partials =
                    partialDAO.findByLdapActorAndUnitId(
                            unit.getId(),
                            actor.getLogin(),
                            actor.getType());
            if (partials != null) {
                partialList.addAll(partials);
            }
            final List<Project> projects =
                    projectDAO.findByLdapActorAndUnitId(
                            unit.getId(),
                            actor.getLogin(),
                            actor.getType());
            if (projects != null) {
                projectList.addAll(projects);
            }
            final List<Remedial> remedials =
                    remedialDAO.findByLdapActorAndUnitId(
                            unit.getId(),
                            actor.getLogin(),
                            actor.getType());
            if (remedials != null) {
                remedialList.addAll(remedials);
            }
        }
    }

    /**
     * adds data into an item.
     *
     * @param item      the item where to add data.
     * @param education the education.
     */
    private void addDataModelItem(final CalendarDataModelReportItemImpl item,
                                  final Education education) {
        item.addData(education.getSubject());

        item.setDay(calendar.get(Calendar.DAY_OF_MONTH));
        item.setEnabled(true);
        item.setStyleClass("");
    }

    /**
     * @param date the date where the tooltip is needed.
     *
     * @return the tooltip object that si displayed.
     */
    @Override
    public final Object getToolTip(final Date date) {
        return null;
    }
}
